/*LICENSE_BEGIN
 * ******************************************************************
 * All original parts of SoccerScope2003 have copyright (2003) by
 * Team YowAI, represented by Mr. Shuhei Shiota
 * The Department of Creative Informatics
 * The Graduate School of Information Science and Technology
 * The University of Tokyo
 * 
 * Additional classes (except libraries in /lib) were developed by 
 * the Dainamite Robocup-Team of the DAI-Labor, TU-Berlin 
 * (www.dai-labor.de)
 * 
 * Extended/new classes/packages are:
 *   soccerscope.analyzer.LogfileAnalyzer
 *   soccerscope.daistatistic.*
 *   soccerscope.daistatistic.charts.*
 *   soccerscope.daistatistic.tools.*
 *   soccerscope.db.*
 *   soccerscope.dialog.*
 *   soccerscope.model.PlayerWorldModel
 *   soccerscope.model.SimplePlayer
 *   soccerscope.net.AgentConnector
 *   soccerscope.training.*
 *   soccerscope.training.conditions.*
 * ******************************************************************
LICENSE_END*/
package soccerscope.dialog;

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.ListSelectionModel;
import javax.swing.border.EtchedBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import soccerscope.model.ClientScene;
import soccerscope.model.PlayMode;
import soccerscope.model.SoccerObject;
import soccerscope.model.WorldModel;
import soccerscope.training.TrainingModel;
import soccerscope.view.SoccerObjectSelectObserver;

public class TrainingSetupDialog extends JDialog implements ActionListener,
		ListSelectionListener, SoccerObjectSelectObserver {

	private static final long serialVersionUID = 6167667904233838593L;

	private JTabbedPane mainTabs;

	private JPanel execPanel;

	private JButton saveScenario;

	private JPanel selectObjectPanel;

	private ObjectTrainingPanel objectTrainingDialog;

	private GameConditionPanel gameConditionPanel;

	private JLabel selDescr;

	private JComboBox selectObjectBox;

	private JButton loadScenario;

	private JPanel buttonPanel;

	private JPanel statisticPanel;

	private JPanel setupPanel;

	private ClientScene scene = null;

	private TrainingModel tm;

	private SoccerObject[] objects = new SoccerObject[23];

	private JList playModeList;

	/**
	 * The constructor creates a reference to the scene and to the main-frame,
	 * because it is a modal dialog. From the scene, all player/ball data,
	 * including the TrainingModels are refered to.
	 * 
	 * @param frame -
	 *            the soccerscope frame
	 * @param scene -
	 *            the actual scene
	 */
	public TrainingSetupDialog(JFrame frame, ClientScene scene) {
		super(frame);
		// this.scene = scene;
		//
		// if (WorldModel.getInstance().trainModel == null) {
		// WorldModel.getInstance().trainModel =
		// new TrainingModel(scene);
		// }
		// tm = WorldModel.getInstance().trainModel;
		//		
		// // set the players and the ball to the array
		// for (int i = 0; i < 22; i++) {
		// objects[i] = this.scene.player[i];
		// }
		// objects[22] = this.scene.ball;
		this.setScene(scene);

		initGUI();
		this.pack();
	}

	/**
	 * This method sets the scene of soccerscope
	 * 
	 * @param scene -
	 *            the actual scene
	 */
	public void setScene(ClientScene scene) {
		this.scene = scene;
		boolean newInst = false;
		if (WorldModel.getInstance().trainModel == null) {
			WorldModel.getInstance().trainModel = new TrainingModel(scene);
			newInst = true;
		}
		this.tm = WorldModel.getInstance().trainModel;

		// set the players and the ball to the array
		for (int i = 0; i < 22; i++) {
			this.objects[i] = this.scene.player[i];
		}
		this.objects[22] = this.scene.ball;

		// refresh GUI vision
		if (!newInst) {
			if (this.objectTrainingDialog != null) {
				this.objectTrainingDialog.setObject(this.objects[0],
						this.tm.objectTrainingModel[0]);
				this.selectObjectBox.setSelectedIndex(0);
			}
		}
	}

	private void initGUI() {
		try {
			{
				BorderLayout thisLayout = new BorderLayout();
				this.getContentPane().setLayout(thisLayout);
				this.setResizable(false);
				this.setTitle("Dainamite Training-Scenario Editor");
				{
					this.mainTabs = new JTabbedPane();
					this.getContentPane().add(this.mainTabs,
							BorderLayout.CENTER);
					{
						this.setupPanel = new JPanel();
						GridBagLayout setupPanelLayout = new GridBagLayout();
						setupPanelLayout.columnWeights = new double[] { 0.1,
								0.1 };
						setupPanelLayout.columnWidths = new int[] { 7, 7 };
						setupPanelLayout.rowWeights = new double[] { 0.1, 0.1 };
						setupPanelLayout.rowHeights = new int[] { 7, 7 };
						this.setupPanel.setLayout(setupPanelLayout);
						this.mainTabs.addTab("Training-Setup", null,
								this.setupPanel, null);
						{
							this.selectObjectPanel = new JPanel();
							GridBagLayout selectObjectPanelLayout = new GridBagLayout();
							selectObjectPanelLayout.columnWeights = new double[] {
									0.1, 0.1 };
							selectObjectPanelLayout.columnWidths = new int[] {
									7, 7 };
							selectObjectPanelLayout.rowWeights = new double[] {
									0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 };
							selectObjectPanelLayout.rowHeights = new int[] { 7,
									7, 7, 7, 7, 7, 7 };
							this.selectObjectPanel
									.setLayout(selectObjectPanelLayout);
							this.setupPanel.add(this.selectObjectPanel,
									new GridBagConstraints(0, 0, 1, 1, 0.0,
											0.0, GridBagConstraints.CENTER,
											GridBagConstraints.BOTH,
											new Insets(0, 0, 0, 0), 0, 0));
							{
								this.selDescr = new JLabel();
								this.selectObjectPanel.add(this.selDescr,
										new GridBagConstraints(0, 0, 1, 1, 0.0,
												0.0, GridBagConstraints.CENTER,
												GridBagConstraints.BOTH,
												new Insets(3, 3, 3, 3), 0, 0));
								this.selDescr.setText("Select Object:");
							}
							{
								ComboBoxModel selectObjectBoxModel = new DefaultComboBoxModel(
										new String[] { "Player 1 [Left]",
												"Player 2 [Left]",
												"Player 3 [Left]",
												"Player 4 [Left]",
												"Player 5 [Left]",
												"Player 6 [Left]",
												"Player 7 [Left]",
												"Player 8 [Left]",
												"Player 9 [Left]",
												"Player 10 [Left]",
												"Player 11 [Left]",

												"Player 1 [Right]",
												"Player 2 [Right]",
												"Player 3 [Right]",
												"Player 4 [Right]",
												"Player 5 [Right]",
												"Player 6 [Right]",
												"Player 7 [Right]",
												"Player 8 [Right]",
												"Player 9 [Right]",
												"Player 10 [Right]",
												"Player 11 [Right]",

												"Ball" });
								this.selectObjectBox = new JComboBox();
								this.selectObjectPanel.add(
										this.selectObjectBox,
										new GridBagConstraints(1, 0, 1, 1, 0.0,
												0.0, GridBagConstraints.CENTER,
												GridBagConstraints.NONE,
												new Insets(3, 3, 3, 3), 0, 0));
								this.selectObjectBox
										.setModel(selectObjectBoxModel);
								this.selectObjectBox.setName("Select Object");
								this.selectObjectBox.addActionListener(this);
							}
							{
								// List With PlayModes:
								JLabel selPlayMode = new JLabel(
										"Select Start-PlayMode:");
								this.selectObjectPanel.add(selPlayMode,
										new GridBagConstraints(0, 1, 2, 1, 0.0,
												0.0,
												GridBagConstraints.SOUTHWEST,
												GridBagConstraints.NONE,
												new Insets(3, 3, 3, 3), 0, 0));

								DefaultListModel playModeListModel = new DefaultListModel();
								for (PlayMode.PLAY_MODE p : PlayMode.allPlayModes)
									playModeListModel.addElement(p);

								this.playModeList = new JList();
								this.playModeList.setBorder(new EtchedBorder());
								this.playModeList
										.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
								this.playModeList.setVisibleRowCount(10);
								this.playModeList.setModel(playModeListModel);
								JScrollPane scrollingList = new JScrollPane(
										this.playModeList);
								this.selectObjectPanel.add(scrollingList,
										new GridBagConstraints(0, 2, 2, 2, 0.0,
												0.0, GridBagConstraints.WEST,
												GridBagConstraints.HORIZONTAL,
												new Insets(3, 3, 3, 3), 0, 0));
								this.playModeList
										.addListSelectionListener(this);
								this.playModeList.setSelectedValue(
										this.tm.startPlayMode, true);
							}
						}
						{
							this.objectTrainingDialog = new ObjectTrainingPanel();
							this.objectTrainingDialog.setObject(
									this.objects[0],
									this.tm.objectTrainingModel[0]);
							this.setupPanel.add(this.objectTrainingDialog,
									new GridBagConstraints(1, 0, 1, 2, 0.0,
											0.0, GridBagConstraints.CENTER,
											GridBagConstraints.BOTH,
											new Insets(0, 0, 0, 0), 0, 0));
						}
					}
					{
						this.gameConditionPanel = new GameConditionPanel(
								this.scene);
						this.mainTabs.addTab("Training-State", null,
								this.gameConditionPanel, null);
					}
					{
						this.statisticPanel = new JPanel();
						this.mainTabs.addTab("Training-Statistics", null,
								this.statisticPanel, null);
					}
					{
						this.execPanel = new JPanel();
						this.mainTabs.addTab("Training-Execution", null,
								this.execPanel, null);
					}
				}
				{
					this.buttonPanel = new JPanel();
					this.getContentPane().add(this.buttonPanel,
							BorderLayout.SOUTH);
					{
						this.loadScenario = new JButton();
						this.buttonPanel.add(this.loadScenario);
						this.loadScenario.setText("Load");
						this.loadScenario.addActionListener(this);
					}
					{
						this.saveScenario = new JButton();
						this.buttonPanel.add(this.saveScenario);
						this.saveScenario.setText("Save");
						this.saveScenario.addActionListener(this);
					}
				}
			}
			this.setSize(600, 500);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * This method listens for changes in the Combo-Box - which will update the
	 * object- training-dialog by setting a new object (ball or player).
	 * 
	 * @param arg0 -
	 *            the event
	 */
	public void actionPerformed(ActionEvent arg0) {
		if (arg0.getSource() == this.selectObjectBox) {
			int index = this.selectObjectBox.getSelectedIndex();
			if (index >= 0)
				this.objectTrainingDialog.setObject(this.objects[index],
						this.tm.objectTrainingModel[index]);
			this.objectTrainingDialog.repaint();
		} else if (arg0.getSource() == this.saveScenario) {
			JFileChooser chooser = new JFileChooser();

			int returnVal = chooser.showOpenDialog(this.getParent());
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				String filename = chooser.getSelectedFile().getAbsolutePath();
				boolean b = TrainingModel.saveTrainingModel(this.tm, filename);
				if (!b) {
					JOptionPane.showMessageDialog(this,
							"Error Saving the file: " + filename, "ERROR",
							JOptionPane.ERROR_MESSAGE);

				}
			}
		} else if (arg0.getSource() == this.loadScenario) {
			JFileChooser chooser = new JFileChooser();

			int returnVal = chooser.showOpenDialog(this.getParent());
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				String filename = chooser.getSelectedFile().getAbsolutePath();
				TrainingModel tm = TrainingModel.loadTrainingModel(filename);
				if (tm != null) {
					WorldModel.getInstance().trainModel = tm;
					this.tm = tm;
					ClientScene cscene = ClientScene.createScene(tm);
					// this.scene = cscene;
					WorldModel.getSceneSet().addTrainingScene(
							cscene);
					this.setVisible(false);
				}
			}
		}
	}

	/**
	 * This method changes the start-playmode of the training-scenario, chosen
	 * from the list <playModeList>!
	 */
	public void valueChanged(ListSelectionEvent arg0) {
		if (arg0.getSource() == this.playModeList
				&& this.playModeList.getSelectedIndex() >= 0) {
			this.tm.startPlayMode = (PlayMode.PLAY_MODE) this.playModeList
					.getSelectedValue();
		}
	}

	/**
	 * This method checks, if a soccer-object was selected on the screen. If so,
	 * it it notified here, and the UI is updated consequently.
	 * 
	 * @param id -
	 *            the ID - corresponds to the entries in the combo-box
	 * @param flat
	 *            true, if selected, false if deselected
	 */
	public void selectSoccerObject(int id, boolean flat) {
		if (!this.isVisible())
			return;
		if (flat) {
			this.objectTrainingDialog.setObject(this.objects[id],
					this.tm.objectTrainingModel[id]);
			this.selectObjectBox.setSelectedIndex(id);
		}
	}

	@Override
	public void setVisible(boolean flag) {
		super.setVisible(flag);

		this.playModeList.setSelectedValue(this.tm.startPlayMode, true);
	}

}
